package org.budo.warehouse.logic.consumer.mail;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.mail.Email;
import org.apache.commons.mail.HtmlEmail;
import org.budo.druid.util.DruidUtil;
import org.budo.graph.annotation.SpringGraph;
import org.budo.support.freemarker.FreemarkerUtil;
import org.budo.support.javax.sql.util.JdbcUtil;
import org.budo.support.lang.util.MapUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.servlet.util.QueryStringUtil;
import org.budo.warehouse.logic.api.AbstractDataConsumer;
import org.budo.warehouse.logic.api.DataMessage;
import org.budo.warehouse.logic.util.EntryBufferUtil;
import org.budo.warehouse.logic.util.PipelineUtil;
import org.budo.warehouse.service.api.IDataNodeService;
import org.budo.warehouse.service.api.IEntryBufferService;
import org.budo.warehouse.service.entity.DataNode;
import org.budo.warehouse.service.entity.EntryBuffer;
import org.budo.warehouse.service.entity.Pipeline;

import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Slf4j
public class MailDataConsumer extends AbstractDataConsumer {
    private static final String TEXT_HTML_CHARSET_UTF_8 = "text/html;charset=UTF-8";

    /**
     * 邮件模板
     */
    private static final String MAIL_TEMPLATE = "<table border=\"1\">" //
            + "<tr>" //
            + "<td>Pipeline</td>" //
            + "<td>EventType</td>" //
            + "<td>SchemaName</td>" //
            + "<td>TableName</td>" //
            + "<td>SQL</td>" //
            + "<td>ROWS</td>" //
            + "<td>CreatedAt</td>" //
            + "</tr>" //
            + "<#list entryBuffers as entryBuffer>" //
            + "<tr>" //
            + "<td>${entryBuffer.pipelineId?c}</td>" //
            + "<td>${entryBuffer.eventType}</td>" //
            + "<td>${entryBuffer.schemaName}</td>" //
            + "<td>${entryBuffer.tableName}</td>" //
            + "<td>${entryBuffer.sql!}</td>" //
            + "<td>${entryBuffer.rows!}</td>" //
            + "<td>${entryBuffer.createdAt}</td>" //
            + "</tr>" //
            + "</#list>" //
            + "</table>";

    @Resource
    private IEntryBufferService entryBufferService;

    @Resource
    private IDataNodeService dataNodeService;

    @SpringGraph
    @Override
    public void consume(DataMessage dataMessage) {
        Pipeline pipeline = this.getPipeline();
        DataNode targetDataNode = dataNodeService.findById(pipeline.getTargetDataNodeId());

        String url = targetDataNode.getUrl();
        String host = JdbcUtil.getHost(url);
        if (null == host || host.trim().isEmpty()) {
            log.error("#106 return, targetDataNode=" + targetDataNode);
            return;
        }

        String username = targetDataNode.getUsername();
        String password = targetDataNode.getPassword();
        password = DruidUtil.rsaDecrypt(password); // 密码解密

        String from = QueryStringUtil.getParameter(url, "from", username); // 默认用username
        String[] to = StringUtil.split(pipeline.getTargetTable(), ";");

        String subject = PipelineUtil.targetSchema(pipeline, null);

        // 邮件服务器配置
        HtmlEmail htmlEmail = new HtmlEmail();
        htmlEmail.setHostName(host);
        htmlEmail.setAuthentication(username, password);

        // 邮件正文
        List<EntryBuffer> entryBuffers = EntryBufferUtil.messageToBuffers(dataMessage, pipeline, true);
        Map<String, Object> map = MapUtil.stringObjectMap("entryBuffers", entryBuffers);
        String mailContent = FreemarkerUtil.freemarkerRender(MAIL_TEMPLATE, map);

        String messageId = this.sendMail(htmlEmail, from, to, subject, mailContent);

        log.info("#103 from=" + from + ", to=" + Arrays.toString(to) + ", subject=" + subject + ", messageId=" + messageId);
    }

    private String sendMail(Email email, String from, String[] to, String subject, String content) {
        try {
            email.addTo(to);
            email.setFrom(from);
            email.setSubject(subject);
            email.setContent(content, TEXT_HTML_CHARSET_UTF_8);

            return email.send(); // messageId
        } catch (Throwable e) {
            log.error("#115 sendMail error, e=" + e, e);
            return null;
        }
    }
}